/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
'use strict'

// Form service
angular.module('flowableModeler').service('FormBuilderService', [
  '$http',
  '$q',
  '$rootScope',
  '$translate',
  '$timeout',
  function($http, $q, $rootScope, $translate, $timeout) {
    // Removes all properties starting with '_', used before json serialization
    function removePrivateFields(fields) {
      var idArr = []
      fields.forEach(function(field, i) {
        idArr.push(field.id)
        for (var attr in field) {
          if (attr.indexOf('_') === 0) {
            delete field[attr]
          }
        }
        //设置元素宽度
        if(!field.layout && $rootScope.cols){
          field.layout = {}
          field.layout.row = $rootScope.cols
        }
        if (field.fields) {
          for (var fieldsName in field.fields) {
            removePrivateFields(field.fields[fieldsName])
          }
        }
      })
      //表单选项id不可重复
      if (
        idArr.some(function(item, index, arr) {
          return idArr.indexOf(item) != index
        })
      ) {
        return false
      }
      return fields
    }

    /**
     * Remove the given step from the given container.
     */
    this.saveForm = function(data, name, formKey, description, saveCallback, errorCallback) {
      var fieldIndex = 0
      for (var i = 0; i < $rootScope.formItems.length; i++) {
        var field = $rootScope.formItems[i]
        this._cleanFormField(field, fieldIndex++)
      }
      var fields = removePrivateFields(angular.copy($rootScope.formItems))
      if (!fields) {
        $rootScope.alerts['current'] = {
          type: 'alert-danger',
          message: $translate.instant('FORM-BUILDER.POPUP.DUPLICATE-ID')
        }
        $timeout(function() {
          $rootScope.alerts['current'] = ''
        }, 3000)
        return
      }
      data.formRepresentation = $rootScope.currentForm
      data.formRepresentation.name = name
      data.formRepresentation.key = formKey

      if (description && description.length > 0) {
        data.formRepresentation.description = description
      }

      var currentActiveTab = $rootScope.formBuilder.activeTab
      if (currentActiveTab != 'design') {
        $rootScope.formBuilder.activeTab = 'design'
      }

      data.formRepresentation.formDefinition = {
        name: name,
        key: formKey,
        fields: fields,
        outcomes: $rootScope.currentOutcomes
      }

      html2canvas(jQuery('#canvasSection'), {
        onrendered: function(canvas) {
          var scale = canvas.width / 300.0
          var extra_canvas = document.createElement('canvas')
          extra_canvas.setAttribute('width', 300)
          extra_canvas.setAttribute('height', canvas.height / scale)
          var ctx = extra_canvas.getContext('2d')
          ctx.drawImage(canvas, 0, 0, canvas.width, canvas.height, 0, 0, 300, canvas.height / scale)
          data.formImageBase64 = extra_canvas.toDataURL('image/png')
          $http({ method: 'PUT', url: FLOWABLE.APP_URL.getFormModelUrl($rootScope.currentForm.id), data: data })
            .success(function(response, status, headers, config) {
              if (saveCallback) {
                saveCallback()
              }
            })
            .error(function(response, status, headers, config) {
              if (errorCallback) {
                errorCallback(response)
              }
            })

          if (currentActiveTab != 'design') {
            $rootScope.formBuilder.activeTab = currentActiveTab
          }
        }
      })
    }

    this._cleanFormField = function(field, fieldIndex) {
      if (!field.overrideId) {
        var fieldId
        if (field.name && field.name.length > 0) {
          fieldId = field.name.toLowerCase()
          fieldId = fieldId.replace(new RegExp(' ', 'g'), '')
          fieldId = fieldId.replace(/[&\/\\#,+~%.'":*?!<>{}()$@;]/g, '')
        } else {
          fieldId = 'field' + fieldIndex
        }
        field.id = fieldId
      }
    }

    /**
     * Updates the form cache for a specific step
     * @param {String} stepId
     * @param {Object} formDefinition
     */
    this.updateFormsCache = function(stepId, formDefinition) {
      if (stepId) {
        if (formDefinition && formDefinition.id) {
          _updateFormCache(stepId, formDefinition.id)
        } else {
          _updateFormCache(stepId)
        }
      }
    }

    /**
     * Fetches forms from cache up to the given step (and not after)
     * @param {Array} steps all steps in sequential order
     * @param {String} stepId the current step
     * @return {Array} flattened list of all forms up to given step
     */
    this.getFormsForStep = function(steps, stepId) {
      var forms = []

      if (stepId !== '__startform') {
        // check start for start form
        forms.push(_getFormForStep('__startform'))

        if (stepId && steps && steps.length > 0) {
          for (var i = 0; i < steps.length; i++) {
            if (steps[i].id != stepId) {
              forms.push(_getFormForStep(steps[i].id))
            } else {
              break
            }
          }
        }
      }

      // only unique forms
      var uniqueIds = []
      var uniqueForms = []

      forms.forEach(function(item) {
        if (item && item.id) {
          if (uniqueIds.indexOf(item.id) < 0) {
            uniqueIds.push(item.id)
            uniqueForms.push(item)
          }
        }
      })

      uniqueForms.sort(function(a, b) {
        return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1
      })

      return uniqueForms
    }

    /**
     * Fetches form outcomes from cache for specific form
     * @param {String} formId
     * @return {Array} flattened list of all form outcomes
     */
    this.getFormOutcomesForForm = function(formId) {
      var outcomes = []
      if (formId) {
        outcomes = _getFormOutcomesForForm(formId)
      }

      outcomes.sort(function(a, b) {
        return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1
      })

      return outcomes
    }

    /**
     * Fetches form fields from cache for specific form
     * @param {String} formId
     * @return {Array} flattened list of all form form fields
     */
    this.getFormFieldsForForm = function(formId) {
      var formFields = []
      if (formId) {
        formFields = _getFormFieldsForForm(formId)
      }
      return formFields
    }

    var _updateFormCache = function(stepId, formId) {
      if (stepId && formId) {
        $http({ method: 'GET', url: FLOWABLE.APP_URL.getFormModelUrl(formId) }).success(function(response) {
          if (response) {
            var outcomes
            var formFields
            if (response.formDefinition) {
              if (response.formDefinition.fields) {
                formFields = response.formDefinition.fields
              }

              if (response.formDefinition.outcomes) {
                outcomes = response.formDefinition.outcomes
              }
            }
            var filteredFormFields = _filterFormFields(formFields)
            var formFieldInfo = {
              id: response.id,
              name: response.name,
              description: response.description,
              outcomes: outcomes,
              fields: filteredFormFields
            }
            _addFormFieldsForStepToCache(stepId, formFieldInfo)
          }
        })
      }
      if (stepId && !formId) {
        _deleteFormFieldsForStepFromCache(stepId)
      }
    }

    var _getFormDefinitions = function(formIds, callback) {
      if (formIds.length > 0) {
        var formIdParams = ''
        for (var i = 0; i < formIds.length; i++) {
          if (formIdParams.length > 0) {
            formIdParams += '&'
          }
          formIdParams += 'formId=' + formIds[i]
        }
        if (formIdParams.length > 0) {
          formIdParams += '&'
        }
        formIdParams += 'version=' + Date.now()

        $http({ method: 'GET', url: FLOWABLE.APP_URL.getFormModelValuesUrl(formIdParams) })
          .success(function(data) {
            if (callback) {
              callback(data)
            }
          })
          .error(function(data) {
            console.log('Something went wrong when fetching form values:' + JSON.stringify(data))
          })
      }
    }
  }
])
